内容由 AI 生成
clickable Avatar: undefined
<template>
  <view class="content">
    <!-- 加载动画 -->
    <view class="loader" v-if="loading">
      <view class="spinner"></view>
    </view>
    
    <view class="header" :class="{ 'header-animation': headerAnimation }">
      <image src="/static/login/logo.png"></image>
    </view>

    <view class="list">
      <view class="list-call" :class="{ 'focused': phoneFocused }">
        <image class="img" src="/static/login/1.png"></image>
        <input
          class="sl-input"
          type="number"
          maxlength="11"
          placeholder="输入手机号"
          v-model="data.phone"
          @focus="phoneFocused = true"
          @blur="phoneFocused = false"
        />
      </view>
      <view class="list-call" :class="{ 'focused': passwordFocused }">
        <image class="img" src="/static/login/2.png"></image>
        <input
          class="sl-input"
          :type="passwordVisible ? 'text' : 'password'"
          maxlength="16"
          placeholder="输入密码"
          v-model="data.password"
          @focus="passwordFocused = true"
          @blur="passwordFocused = false"
        />
        <image
          class="eye-icon"
          :src="passwordVisible ? '/static/login/op.png' : '/static/login/cl.png'"
          @tap="togglePasswordVisible"
        ></image>
      </view>
      
      <!-- 记住密码选项 -->
      <view class="remember-password">
        <checkbox 
          :checked="rememberPassword" 
          @change="toggleRememberPassword"
        ></checkbox>
        <text>记住密码</text>
      </view>
    </view>

    <view
      class="button-login"
      hover-class="button-hover"
      @tap="bindLogin"
      :class="{ 'button-animation': buttonAnimation }"
    >
      <text>登录</text>
    </view>

    <view class="agreenment">
      <navigator url="/pages/login/findPassword" open-type="navigate">忘记密码</navigator>
      <text>|</text>
      <navigator url="/pages/login/register" open-type="navigate">注册账户</navigator>
    </view>

    <!-- 其他登录方式 -->
    <view class="other-login">
      <view class="other-login-title">其他登录方式</view>
      <view class="other-login-icons">
        <view class="icon-wechat" @tap="wechatLogin">
          <uni-icons type="weixin" size="40" color="#09BB07"></uni-icons>
        </view>
        <view class="icon-qq" @tap="qqLogin">
          <uni-icons type="qq" size="40" color="#12B7F5"></uni-icons>
        </view>
        <view class="icon-weibo" @tap="weiboLogin">
          <uni-icons type="weibo" size="40" color="#E6162D"></uni-icons>
        </view>
      </view>
    </view>
  </view>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import { ApiLogin } from '../api/user';
import {useAuthStore} from "../../store/token.js"

// 定义数据
const data = ref({
  phone: "",
  password: ""
})
const passwordVisible = ref(false);
const loading = ref(false);
const headerAnimation = ref(false);
const phoneFocused = ref(false);
const passwordFocused = ref(false);
const buttonAnimation = ref(false);
const rememberPassword = ref(false); // 记住密码状态

// 页面加载时检查缓存
onMounted(() => {
  headerAnimation.value = true;
  checkRememberedCredentials();
});

// 检查缓存中是否保存了登录信息
const checkRememberedCredentials = () => {
  const cachedCredentials = uni.getStorageSync('rememberedCredentials');
  if (cachedCredentials) {
    data.value.phone = cachedCredentials.phone;
    data.value.password = cachedCredentials.password;
    rememberPassword.value = true;
  }
};

// 切换记住密码状态
const toggleRememberPassword = (e) => {
  rememberPassword.value = e.detail.value;
};

// 切换密码可见性
const togglePasswordVisible = () => {
  passwordVisible.value = !passwordVisible.value;
};

// 绑定登录按钮点击事件的函数
const bindLogin = async () => {
  // 添加按钮动画
  buttonAnimation.value = true;
  
  // 验证手机号格式是否正确
  if (!/^1[3-9]\d{9}$/.test(data.value.phone)) {
    // 重置按钮动画
    buttonAnimation.value = false;
    
    // 显示提示信息
    uni.showToast({
      icon: 'none',
      title: '手机号格式不正确',
    });
    return;
  }
  // 验证密码是否符合要求（8-16位，包含数字和字母）
  if (data.value.password.length < 8 || data.value.password.length > 16 || !(/[A-Za-z]/.test(data.value.password)) || !(/[0-9]/.test(data.value.password))) {
    // 重置按钮动画
    buttonAnimation.value = false;
    
    // 显示提示信息
    uni.showToast({
      icon: 'none',
      title: '密码必须为8-16位，包含数字和字母',
    });
    return;
  }

  
  // 显示加载动画
  loading.value = true;

  try {
    let res = await ApiLogin(data.value);
    
    // 保存或清除记住密码信息
    if (rememberPassword.value) {
      uni.setStorageSync('rememberedCredentials', {
        phone: data.value.phone,
        password: data.value.password
      });
    } else {
      uni.removeStorageSync('rememberedCredentials');
    }
    
    // 重置按钮动画
    buttonAnimation.value = false;
    
    // 隐藏加载动画
    loading.value = false;
    
    // 登录成功逻辑
    uni.showToast({
      icon: 'none',
      title: '登录成功',
    });
    
    // 跳转到主页
    uni.navigateTo({
      url: "/pages/tabbar/tabbar"
    });
     // 获取 Pinia store
    const authStore = useAuthStore();
	 authStore.setToken(res);
  } catch (error) {
    // 重置按钮动画
    buttonAnimation.value = false;
    // 隐藏加载动画
    loading.value = false;
  }
};

// 第三方登录方法
const wechatLogin = () => {
  uni.showToast({
    icon: 'none',
    title: '微信登录',
  });
  // 这里添加微信登录逻辑
};

const qqLogin = () => {
  uni.showToast({
    icon: 'none',
    title: 'QQ登录',
  });
  // 这里添加QQ登录逻辑
};

const weiboLogin = () => {
  uni.showToast({
    icon: 'none',
    title: '微博登录',
  });
  // 这里添加微博登录逻辑
};
</script>

<style lang="less" scoped>
/* 重置 body 样式 */
body {
  margin: 0;
  padding: 0;
  overflow: hidden; /* 禁止 body 滚动 */
}

/* 主容器样式 */
.content {
  position: fixed; /* 使用固定定位 */
  top: 0;
  left: 0;
  width: 100%;
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  // background-image: url('/static/login/bg.png');
  background-image: url('https://wimg.588ku.com/gif320/24/07/09/fb8a6824ff224f7ca969c6f0eaa82062.gif');
  background-size: cover;
  background-position: center;
  overflow: hidden; /* 禁止滚动 */
  z-index: 1;
}

/* 加载动画 */
.loader {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(255, 255, 255, 0.9);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 100;
}

.spinner {
  width: 60rpx;
  height: 60rpx;
  border: 6rpx solid rgba(63, 205, 235, 0.2);
  border-radius: 50%;
  border-top-color: #3fcdeb;
  animation: spin 1s ease-in-out infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* 头部动画 */
.header {
  width: 161rpx;
  height: 161rpx;
  border-radius: 50%;
  margin-top: 40rpx;
  margin-bottom: 60rpx;
  transition: all 0.5s ease;
  box-shadow: 0rpx 12rpx 24rpx 0rpx rgba(0, 0, 0, 0.1);
  background-color: transparent;
  overflow: hidden;
  transform-style: preserve-3d;
}

.header image {
  width: 161rpx;
  height: 161rpx;
  border-radius: 50%;
  transition: transform 0.5s ease;
}

.header-animation {
  animation: header-float 3s ease-in-out infinite, header-rotate 10s linear infinite;
}

@keyframes header-float {
  0%, 100% { transform: translateY(0) rotate(0deg); }
  50% { transform: translateY(-10rpx) rotate(5deg); }
}

@keyframes header-rotate {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

/* 输入框样式 */
.list {
  display: flex;
  flex-direction: column;
  width: 100%;
  max-width: 500rpx;
}

.list-call {
  display: flex;
  flex-direction: row;
  align-items: center;
  height: 90rpx;
  margin-bottom: 30rpx;
  background-color: rgba(255, 255, 255, 0.95);
  border-radius: 45rpx;
  padding: 0 30rpx;
  box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.08);
  transition: all 0.3s ease;
  border: 1px solid transparent;
}

.list-call.focused {
  box-shadow: 0 8rpx 20rpx rgba(63, 205, 235, 0.3);
  transform: translateY(-3rpx);
  border-color: #3fcdeb;
}

.list-call .img {
  width: 40rpx;
  height: 40rpx;
  margin-right: 20rpx;
  transition: transform 0.3s ease, filter 0.3s ease;
}

.list-call.focused .img {
  transform: scale(1.1) rotate(5deg);
  filter: drop-shadow(0 0 5px rgba(63, 205, 235, 0.5));
}

.list-call .sl-input {
  flex: 1;
  text-align: left;
  font-size: 32rpx;
  color: #333;
  transition: all 0.3s ease;
  background: transparent;
}

.list-call.focused .sl-input {
  color: #3fcdeb;
  text-shadow: 0 0 5px rgba(63, 205, 235, 0.2);
}

.eye-icon {
  width: 40rpx;
  height: 40rpx;
  transition: all 0.3s ease;
}

.list-call.focused .eye-icon {
  transform: scale(1.1) rotate(-5deg);
}

/* 记住密码样式 */
.remember-password {
  display: flex;
  align-items: center;
  margin-left: 50rpx;
  margin-bottom: 20rpx;
  color: #888;
  font-size: 28rpx;
}

.remember-password checkbox {
  transform: scale(0.7);
  margin-right: 10rpx;
}

/* 登录按钮样式 */
.button-login {
  color: white;
  font-size: 34rpx;
  width: 470rpx;
  height: 100rpx;
  background: linear-gradient(45deg, #4b97f0, #3fcdeb);
  border-radius: 50rpx;
  line-height: 100rpx;
  text-align: center;
  margin: 30rpx auto 40rpx; /* 调整了外边距，使按钮向上移动 */
  box-shadow: 0 12rpx 24rpx rgba(63, 205, 235, 0.3);
  transition: all 0.3s ease;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  will-change: transform, box-shadow; /* 硬件加速 */
  border: none; /* 移除边框 */
  outline: none; /* 移除轮廓 */
  transform-style: preserve-3d;
}

.button-login::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(45deg, transparent, rgba(255, 255, 255, 0.2), transparent);
  transition: left 0.5s ease;
}

.button-login:hover::before {
  left: 100%;
}

.button-hover {
  transform: translateY(-5rpx);
  box-shadow: 0 16rpx 32rpx rgba(63, 205, 235, 0.4);
}

.button-animation {
  animation: button-pulse 1s ease infinite, button-shine 2s ease-in-out infinite;
}

@keyframes button-pulse {
  0% {
    transform: scale(1);
    box-shadow: 0 12rpx 24rpx rgba(63, 205, 235, 0.3);
  }
  50% {
    transform: scale(0.95);
    box-shadow: 0 8rpx 20rpx rgba(63, 205, 235, 0.5);
  }
  100% {
    transform: scale(1);
    box-shadow: 0 12rpx 24rpx rgba(63, 205, 235, 0.3);
  }
}

@keyframes button-shine {
  0% {
    background-position: -100% 0;
  }
  100% {
    background-position: 100% 0;
  }
}
.button-login {
  background: linear-gradient(45deg, #4b97f0, #3fcdeb);
  background-size: 200% 100%;
}
/* 登录按钮悬停效果 */
.button-login:hover {
  background: linear-gradient(45deg, #3a81d9, #36b9d0);
}
/* 登录按钮按下效果 */
.button-login:active {
  transform: scale(0.95);
  box-shadow: 0 5rpx 15rpx rgba(63, 205, 235, 0.3);
}

/* 链接样式 */
.agreenment {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
  font-size: 26rpx;
  color: #888;
  margin-bottom: 40rpx;
}

.agreenment navigator {
  color: #3fcdeb;
  margin: 0 15rpx;
  position: relative;
  transition: color 0.3s ease, text-shadow 0.3s ease;
}

.agreenment navigator::after {
  content: '';
  position: absolute;
  bottom: -5rpx;
  left: 0;
  width: 0;
  height: 2rpx;
  background-color: #3fcdeb;
  transition: width 0.3s ease;
}

.agreenment navigator:hover {
  color: #2a8cb0;
  text-shadow: 0 0 5px rgba(63, 205, 235, 0.5);
}

.agreenment navigator:hover::after {
  width: 100%;
}

.agreenment text {
  font-size: 24rpx;
  margin: 0 10rpx;
}

/* 其他登录方式 */
.other-login {
  margin-top: 60rpx;
  width: 100%;
  max-width: 500rpx;
}

.other-login-title {
  text-align: center;
  font-size: 28rpx;
  color: #888;
  margin-bottom: 30rpx;
  position: relative;
}

.other-login-title::before,
.other-login-title::after {
  content: '';
  position: absolute;
  top: 50%;
  width: 100rpx;
  height: 1px;
  background: linear-gradient(90deg, transparent, #ddd, transparent);
}

.other-login-title::before {
  left: 20%;
}

.other-login-title::after {
  right: 20%;
}

.other-login-icons {
  display: flex;
  justify-content: center;
  align-items: center;
}

.icon-wechat,
.icon-qq,
.icon-weibo {
  width: 80rpx;
  height: 80rpx;
  margin: 0 20rpx;
  display: flex;
  justify-content: center;
  align-items: center;
  border-radius: 50%;
  cursor: pointer;
  transition: transform 0.3s ease, box-shadow 0.3s ease;
  will-change: transform, box-shadow; /* 硬件加速 */
}

.icon-wechat {
  background-color: rgba(9, 187, 7, 0.1);
}

.icon-qq {
  background-color: rgba(18, 183, 245, 0.1);
}

.icon-weibo {
  background-color: rgba(230, 22, 45, 0.1);
}

.icon-wechat:hover,
.icon-qq:hover,
.icon-weibo:hover {
  transform: scale(1.1);
  box-shadow: 0 0 15rpx rgba(63, 205, 235, 0.5);
}

/* 隐藏滚动条 */
.content::-webkit-scrollbar {
  display: none; /* 隐藏 Webkit 浏览器的滚动条 */
}
</style>